import {InvokeCodeService} from './invoke-code-service';
import {InvokeUtils} from '../../utils/invoke-utils';
import {InvokeDataRest} from '../../entity/invoke-data-rest';

export class JavaScriptInvokeCodeService implements InvokeCodeService {
    getCode(data: InvokeDataRest): string {
        const code = [];
        code.push('```javascript\n');

        if (data.method === 'POST' && data.requestBody && data.requestBody.rawDataType === 'form-data') {
            code.push('var form = new FormData();\n');
            data.requestBody.formData.forEach(item => {
               if (item.key) {
                   code.push(`form.append("${item.key}", "${item.value}");\n`);
               }
            });
            code.push('\n');
        }

        code.push('var settings = {\n');
        code.push('\t"async": true,\n');
        code.push('\t"crossDomain": true,\n');
        code.push('\t"url": "');
        code.push(InvokeUtils.getUrl(data));
        code.push('",\n');
        code.push('\t"method": "');
        code.push(data.method);
        code.push('",\n');

        const headerKeys = new Set();
        let hasHeader = false;
        if (data.headers) {
            data.headers.forEach(header => {
                if (header.key.length === 0) {
                    return;
                }
                if (!hasHeader) {
                    code.push('\t"headers": {\n');
                    hasHeader = true;
                }
                if (headerKeys.has(header.key)) {
                    return;
                }
                headerKeys.add(header.key);
                this.addHeader(code, header);
            });
        }
        if (data.env.headers) {
            data.env.headers.forEach(header => {
                if (header.key.length === 0 || headerKeys.has(header.key)) {
                    return;
                }
                headerKeys.add(header.key);
                this.addHeader(code, header);
            });
        }
        if (hasHeader) {
            code.splice(code.length - 1, 1);
            code.push('\n\t},\n');
        }
        code.push('\t"data": ');

        let hasPostBody = false;
        if (data.method === 'POST' && data.requestBody) {
            if (data.requestBody.rawDataType === 'raw' && data.requestBody.rawData) {
                this.renderRawCommend(code, data);
            } else {
                if (data.requestBody.rawDataType === 'x-www-form-urlencoded') {
                    this.renderFormUrlEncodedCommend(code, data);
                } else if (data.requestBody.rawDataType === 'form-data') {
                    this.renderFormDataCommend(code, data);
                }
            }
            hasPostBody = true;
        }
        code.push('\n');

        code.push('};\n\n');
        code.push('$.ajax(settings).done(function (response) {\n');
        code.push('\tconsole.log(response);\n');
        code.push('});\n');

        code.push('```');
        return code.join('');
    }

    private addHeader(code: string[], header) {
        code.push('\t\t"');
        code.push(header.key);
        code.push('": "');
        code.push(header.value);
        code.push('"');
        code.push(',\n');
    }

    private renderRawCommend(code: string[], data: InvokeDataRest) {
        code.push(JSON.stringify(data.requestBody.rawData));
    }

    private renderFormUrlEncodedCommend(code: string[], data: InvokeDataRest) {
        const formData = [];
        data.requestBody.formData.forEach(item => {
            if (item.key) {
                formData.push(`\t\t"${item.key}": "${item.value}"`);
            }
        });
        if (formData) {
            code.push('{\n');
            code.push(formData.join(',\n'));
            code.push('\n\t}');
        }
    }

    private renderFormDataCommend(code: string[], data: InvokeDataRest) {
        code.push('form');
    }
}
